package com.brush.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.brush.app.domain.AppAd;
import com.brush.app.domain.req.Ad.add.AppAdvertiseAddReq;
import com.brush.app.domain.req.Ad.edit.AppAdEditReq;
import com.brush.app.domain.req.Ad.query.AppAdQueryReq;
import com.brush.app.domain.resp.Ad.AppAdResp;
import com.brush.app.service.AppAdService;
import com.brush.app.mapper.AppAdMapper;
import com.brush.common.exception.database.PrimaryKeyException;
import com.brush.common.exception.database.RecordNotFoundException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
* @author ckq
* @description 针对表【app_ad(广告轮播图表)】的数据库操作Service实现
* @createDate 2024-10-31 15:25:11
*/
@Service
public class AppAdServiceImpl extends ServiceImpl<AppAdMapper, AppAd>
    implements AppAdService{

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public PageInfo<AppAdResp> paginationQuery(AppAdQueryReq req) {
        return PageHelper.startPage(req.getPageNum(),req.getPageSize()).doSelectPageInfo(()->{
            this.baseMapper.paginationQuery(req);
        });
    }

    @Override
    public AppAdResp findById(Long id) {
        AppAdResp db = this.baseMapper.findById(id);
        if (Objects.isNull(db)) {
            throw new RecordNotFoundException();
        }
        return db;
    }

    @Override
    public boolean add(AppAdvertiseAddReq req) {
        //检验广告name是否存在
        if (this.baseMapper.exists(new LambdaQueryWrapper<AppAd>().eq(AppAd::getName, req.getName()))) {
            throw new RecordNotFoundException();
        }
        AppAd newEntity = new AppAd();
        BeanUtils.copyProperties(req, newEntity);
        return this.save(newEntity);
    }

    @Override
    public boolean edit(AppAdEditReq req) {
        AppAd appAd = this.getById(req.getId());
        if (Objects.isNull(appAd)){
            throw new RecordNotFoundException();
        }
        appAd.setId(req.getId());
        appAd.setName(req.getName());
        appAd.setLink(req.getLink());
        appAd.setImageUrl(req.getImageUrl());
        appAd.setEndTime(req.getEndTime());
        appAd.setStatus(req.getStatus());
        appAd.setDelFlag(req.getDelFlag());
        return this.updateById(appAd);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteById(Long[] ids) {
        final AppAdServiceImpl appAdService = this;
        if (Objects.isNull(ids) || ids.length == 0) {
            throw new PrimaryKeyException();
        }
        this.redisTemplate.execute(new SessionCallback<Void>() {
            @Override
            public Void execute(RedisOperations operations) throws DataAccessException {
                // 开启redis事务
                operations.multi();

                // 循环删除，因为数据量不大, 时间复杂度O(n), 事务问题
                try {
                    for (Long id : ids) {
                        AppAd db = appAdService.getById(id);
                        if (Objects.nonNull(db)) {
                            //删除数据库中的值
                            appAdService.removeById(id);
                            //移出缓存中的值
                            String redisKey = " "+db.getId();
                            operations.delete(redisKey);
                        }
                    }
                    // 提交redis事务
                    operations.exec();

                } catch (Exception e) {
                    operations.discard();
                    throw e;
                }
                return null;
            }
        });
        return true;
    }
}




